/*!
   \file

   \brief
      Base component class. Components are managed by, and interact with, game systems.

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include "Util/typedefs.hpp"

class Entity;

class ComponentOwnerSetter;

/*!
   \brief
      The most basic part of the engine. Components are fragments of system functionality.
*/
class Component
{
public:
   Component( Entity * Owner );

   void Register();

   virtual void Update( double Elapsed ) {}

   virtual ~Component() {}

   void Delete();

   Entity * GetOwner() const;

   uint32_t GetHandle() const;

   void Disable();

   void Enable();

   bool IsEnabled() const;

protected:

   /*!
      \brief
         Override this function if your component needs to do special work to enable itself after
         being disabled.

         For example, a physics component might need to manually add its rigid body back to the
         physics system.
   */
   virtual void EnableComponent() {};
   /*!
      \brief
         Override this function if your component needs to do special work to ensure it's disabled.

         For example, a physics component might need to manually remove its rigid body from the
         physics system.
   */
   virtual void DisableComponent() {};

   /*!
      \brief
         Overload this in a component concrete class, for example, gcModel. This function should
         register this specific type of component with the system responsible for it.
   */
   virtual uint32_t RegisterConcreteClassWithSystem() = 0;

   /*!
      \brief
         Overload this in a component system class, for example, gcBase. This function should
         remove this component from the system responsible for it.
         The system's RemoveComponent function result in this component automatically being
         deallocated at the end of the system's Update function.
   */
   virtual void RemoveComponentFromSystem() = 0;

protected:
   friend class ComponentOwnerSetter;

   void SetOwner( Entity * NewOwner );
private:
   // This component's handle
   uint32_t handle;
   // The entity that owns this component
   Entity * owner;

   bool enabled;
   bool queuedForDelete;
};
